package com.ibeeking.found.upms.b.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ibeeking.found.common.entity.CurrentUser;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.upms.b.rest.service.ICpRoleService;
import com.ibeeking.found.upms.b.rest.service.ICpUserRoleService;
import com.ibeeking.found.upms.b.rest.service.ICpUserService;
import com.ibeeking.found.upms.service.common.bo.CpUserRoleBO;
import com.ibeeking.found.upms.service.common.bo.TenantUserBO;
import com.ibeeking.found.upms.service.common.dos.CpUserRoleDO;
import com.ibeeking.found.upms.service.common.param.RoleUserParam;
import com.ibeeking.found.upms.service.common.param.UserRoleParam;
import com.ibeeking.found.upms.service.mapper.CpUserRoleMapper;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.json.JsonUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName CsUserRoleServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-05-10 9:54
 **/
@Service
public class CpUserRoleServiceImpl implements ICpUserRoleService {

    @Resource
    private CpUserRoleMapper cpUserRoleMapper;
    @Resource
    private ICpRoleService cpRoleServiceImpl;
    @Resource
    private ICpUserService cpUserServiceImpl;

    @Transactional(rollbackFor = {BusinessException.class})
    @Override
    public Boolean modifyUserRoleByUserId(CurrentUser currentUser, UserRoleParam param) {
        if (currentUser.getId().equals(param.getUserId())) {
            throw new BusinessException("禁止修改自己的角色");
        }
        TenantUserBO csUserBO = cpUserServiceImpl.queryById(param.getUserId());
        if (PublishStatusEnum.DISABLE.getValue().equals(csUserBO.getPublishStatus()) || PublishStatusEnum.DISABLE.getValue().equals(csUserBO.getJob())) {
            throw new BusinessException("用户已离职或被锁定，禁止配置角色");
        }
        //查询管理员
        Long administratorId = cpRoleServiceImpl.selectAdministratorId();
        List<Long> userIds = queryUserIdsByRoleId(administratorId).stream().map(CpUserRoleBO::getUserId).collect(Collectors.toList());

        cpUserRoleMapper.delete(new LambdaQueryWrapper<>(CpUserRoleDO.class)
                .eq(CpUserRoleDO::getUserId, param.getUserId()));

        // 1. 查询现有用户角色id列表
        List<CpUserRoleBO> csUserRoleBos = queryRoleIdsByUserId(currentUser.getId());
        List<Long> haveRoleIds = csUserRoleBos.stream().map(CpUserRoleBO::getRoleId).collect(Collectors.toList());
        if (null == param.getRoleIds() || 0 == param.getRoleIds().length) {
            if (haveRoleIds.contains(administratorId)) {
                throw new BusinessException("超级管理员至少要有1个用户");
            }
            return true;
        }
        List<Long> paramIds = Arrays.asList(param.getRoleIds());
        if (paramIds.contains(administratorId) && 0 != userIds.size() && !userIds.contains(currentUser.getId())) {
            throw new BusinessException("超级管理员至多只能有1个用户");
        }
        //新增关系
        List<CpUserRoleDO> saves = new ArrayList<>();
        paramIds.stream().forEach(key -> {
            CpUserRoleDO userRoleDO = new CpUserRoleDO();
            userRoleDO.setRoleId(key);
            userRoleDO.setUserId(param.getUserId());

            saves.add(userRoleDO);
        });
        // 新增关系
        cpUserRoleMapper.insertBatchSomeColumn(saves);
        return true;
    }

    @Override
    public List<CpUserRoleBO> queryRoleIdsByUserId(Long userId) {
        List<CpUserRoleDO> userRoleDoS = cpUserRoleMapper.selectList(new LambdaQueryWrapper<>(CpUserRoleDO.class).eq(CpUserRoleDO::getUserId, userId));
        if (Collections3.isEmpty(userRoleDoS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(userRoleDoS, CpUserRoleBO.class);
    }

    @Transactional(rollbackFor = {BusinessException.class})
    @Override
    public Boolean modifyUserRoleByRoleId(CurrentUser currentUser, RoleUserParam param) {
        cpUserRoleMapper.delete(new LambdaQueryWrapper<>(CpUserRoleDO.class)
                .eq(CpUserRoleDO::getRoleId, param.getRoleId()));

        Long administratorId = cpRoleServiceImpl.selectAdministratorId();
        if (null == param.getUserIds() || 0 == param.getUserIds().length) {
            if (param.getRoleId().equals(administratorId)) {
                throw new BusinessException("超级管理员至少选择一个用户");
            }
            return true;
        }
        List<Long> paramIds = Arrays.asList(param.getUserIds());
        if (param.getRoleId().equals(administratorId) && paramIds.size() > 1) {
            throw new BusinessException("超级管理员至多选择一个用户");
        }
        //新增关系
        List<CpUserRoleDO> saves = new ArrayList<>();
        paramIds.parallelStream().forEach(key -> {
            CpUserRoleDO userRoleDO = new CpUserRoleDO();
            userRoleDO.setRoleId(param.getRoleId());
            userRoleDO.setUserId(key);

            saves.add(userRoleDO);
        });
        cpUserRoleMapper.insertBatchSomeColumn(saves);
        return true;
    }

    @Override
    public List<CpUserRoleBO> queryUserRoleByUserIds(List<Long> userIds) {
        List<CpUserRoleDO> cpUserRoleDos = cpUserRoleMapper.selectList(new LambdaQueryWrapper<>(CpUserRoleDO.class)
                .in(CpUserRoleDO::getUserId, userIds)
        );
        return JsonUtils.jsonToList(cpUserRoleDos, CpUserRoleBO.class);
    }
    @Override
    public List<CpUserRoleBO> queryUserIdsByRoleId(Long roleId) {
        List<CpUserRoleDO> userRoleDoS = cpUserRoleMapper.selectList(new LambdaQueryWrapper<>(CpUserRoleDO.class).eq(CpUserRoleDO::getRoleId, roleId));
        if (Collections3.isEmpty(userRoleDoS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(userRoleDoS, CpUserRoleBO.class);
    }

    @Override
    public Boolean delByUserId(Long userId) {
        return cpUserRoleMapper.delete(new LambdaUpdateWrapper<>(CpUserRoleDO.class).eq(CpUserRoleDO::getUserId, userId)) > 0;
    }

    @Override
    public Boolean delByRoleId(Long roleId) {
        return cpUserRoleMapper.delete(new LambdaUpdateWrapper<>(CpUserRoleDO.class).eq(CpUserRoleDO::getRoleId, roleId)) > 0;
    }

    @Override
    public List<CpUserRoleBO> queryRoleIdsByUserIds(List<Long> userIds) {
        List<CpUserRoleDO> userRoleDoS = cpUserRoleMapper.selectList(new LambdaQueryWrapper<>(CpUserRoleDO.class).in(CpUserRoleDO::getUserId, userIds));
        if (Collections3.isEmpty(userRoleDoS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(userRoleDoS, CpUserRoleBO.class);
    }

    @Override
    public List<CpUserRoleBO> queryUserIdsByRoleIds(List<Long> roleIds) {
        List<CpUserRoleDO> userRoleDoS = cpUserRoleMapper.selectList(new LambdaQueryWrapper<>(CpUserRoleDO.class).in(CpUserRoleDO::getRoleId, roleIds));
        if (Collections3.isEmpty(userRoleDoS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(userRoleDoS, CpUserRoleBO.class);
    }
}
